package com.example.demo.base.thread.juc;

import org.junit.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * @program: java_base
 * @description: CountDownLatch ? demo
 * @author: zhouhongtao
 * @happyCreateTime: 2022/01/26 09:12
 * CountDownLatch 倒计时锁
 * CyclicBarrier  篱栅
 * Semaphore 信号灯
 * 原文：https://www.cnblogs.com/dolphin0520/p/3920397.html
 */
public class CountDownLatchDemo {
// CountDownLatch类位于java.util.concurrent包下，利用它可以实现类似计数器的功能。
// 比如有一个任务A，它要等待其他4个任务执行完毕之后才能执行，此时就可以利用CountDownLatch来实现这种功能了。
// public CountDownLatch(int count) {  };  //参数count为计数值
// public void await() throws InterruptedException { };   //调用await()方法的线程会被挂起，它会等待直到count值为0才继续执行
// public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  //和await()类似，只不过等待一定的时间后count值还没变为0的话就会继续执行
// public void countDown() { };  //将count值减1

    @Test
    public void testDemo1(){
        final CountDownLatch latch = new CountDownLatch(2);

        new Thread(){
            @Override
            public void run() {
                try {
                    System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
                    Thread.sleep(3000);
                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
                    latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        }.start();

        new Thread(){
            @Override
            public void run() {
                try {
                    System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
                    Thread.sleep(3000);
                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
                    latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        }.start();

        try {
            System.out.println("等待2个子线程执行完毕...");
            latch.await();
            System.out.println("2个子线程已经执行完毕");
            System.out.println("继续执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void testFromJDK(){

    }
}

// --------- demo from jdk  demo 1 -----------------

class Driver {
    void main() throws InterruptedException {
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(8);

        for (int i = 0; i < 8; ++i) {// create and start threads
            new Thread(new Worker(startSignal, doneSignal)).start();
        }
       // doSomethingElse();            // don't let run yet
        startSignal.countDown();      // let all threads proceed
       // doSomethingElse();
        doneSignal.await();           // wait for all to finish
    }
}

class Worker implements Runnable {
    private final CountDownLatch startSignal;
    private final CountDownLatch doneSignal;
    Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
        this.startSignal = startSignal;
        this.doneSignal = doneSignal;
    }

    @Override
    public void run() {
        try {
            startSignal.await();
            doWork();
            doneSignal.countDown();
        } catch (InterruptedException ex) {} // return;
    }

    void doWork() {

    }

}


// --------- demo from jdk  demo 1 -----------------
class Driver2 { // ...
    void main() throws InterruptedException {
        CountDownLatch doneSignal = new CountDownLatch(8);
        Executor e = Executors.newFixedThreadPool(8);

        for (int i = 0; i < 8; ++i) { // create and start threads
            e.execute(new WorkerRunnable(doneSignal, i));
        }
        doneSignal.await();           // wait for all to finish
    }
}

class WorkerRunnable implements Runnable {
    private final CountDownLatch doneSignal;
    private final int i;
    WorkerRunnable(CountDownLatch doneSignal, int i) {
        this.doneSignal = doneSignal;
        this.i = i;
    }
    @Override
    public void run() {
        doWork();
        doneSignal.countDown();
    }

    void doWork() {

    }
}


